package com.itranswarp.learnjava;

import java.time.ZoneId;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.itranswarp.learnjava.service.MailSession;
import com.itranswarp.learnjava.service.User;
import com.itranswarp.learnjava.service.UserService;
import org.springframework.context.annotation.Scope;

@Configuration
@ComponentScan
public class AppConfig {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);
        userService.register("sam@example.com", "password", "Sam");
        User user = userService.login("sam@example.com", "password");
        System.out.println(user.getName());
        // 测试MailSession是否单例:
        context.getBean(MailSession.class);
        context.getBean(MailSession.class);
        context.getBean(MailSession.class);
        // 关闭ApplicationContext: 这行代码的作用是：将 context 强制转换为
        // ConfigurableApplicationContext，
        // 然后调用其 close() 方法，关闭 Spring 容器。
        // 3. 为什么要手动关闭？
        // 在 Web 应用中，Spring 容器会随着服务器的启动和关闭自动管理，不需要手动关闭。
        // 在普通 Java 应用（如 main 方法启动的）中，Spring 容器不会自动关闭。此时如果你需要释放资源，就要手动调用 close()。
        ((ConfigurableApplicationContext) context).close();

    }

    // 在 Spring 框架中，@Bean注解用于声明一个由 Spring 容器管理的Bean（组件），
    // 相当于 XML 配置中的<bean>标签。
    // 它通常与@Configuration注解配合使用，在 Java 配置类中定义 Bean。
    // @Bean 返回的Bean仍然是单例。
    // 定义两个ZoneId:注解@Primary
    // 定义两个ZoneId:注解@Qualifier
    // 定义两个ZoneId:注解@Primary：意思是当有多个相同类型的Bean时，优先使用被注解为@Primary的Bean。
    // 定义两个ZoneId:注解@Qualifier：意思是当有多个相同类型的Bean时，通过@Qualifier注解限定Bean的ID，找到需要的Bean。

    // 与 @Component 的区别
    // @Bean                               @Component
    // 在@Configuration类中声明           在类上直接声明
    // 手动定义 Bean 创建逻辑              自动扫描和注册
    // 灵活控制 Bean 创建过程              适合简单组件
    // 通常用于集成第三方组件               适合自定义开发的组件
    @Bean("customService") // 指定Bean名称为"customService"
    @Scope("prototype") // 设置作用域为每次请求创建新实例
    @Primary
    @Qualifier("z")
    ZoneId createZoneOfZ() {
        return ZoneId.of("Z");
    }

    @Bean
    @Qualifier("utc8")
    ZoneId createZoneOfUTC8() {
        return ZoneId.of("UTC+08:00");
    }
}
